﻿/*
 * Cratos Server - Windows Service
 * Cratos Windows Service class
 * 
 * Copyright (c) 2011 Draco
 * 
 * This file is part of Cratos.
 * 
 * Cratos is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * Cratos is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Cratos.  If not, see <http://www.gnu.org/licenses/>.
 * 
 *       .==.        .==.
 *      //'^\\      //^'\\
 *     // ^ ^\(\__/)/^ ^^\\
 *    //^ ^^ ^/6  6\ ^^ ^ \\
 *   //^ ^^ ^/( .. )\^ ^ ^ \\
 *  // ^^ ^/\| V""V|/\^ ^ ^ \\
 * //^^/\/ /  '~~'  \ \/\^ ^ \\
 *  ------------------------------------
 *  HERE BE DRAGONS
 *  
 *  Johan Dercksen - johan@draco.co.za
 */
using System;
using System.Data;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.ServiceModel;
using System.Configuration;
using System.ComponentModel;
using System.ServiceProcess;
using System.Collections.Generic;

using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

using Cratos.Desktop;
using Cratos.Tools.General;
using Cratos.Tools.DataObject;
using Cratos.Server.WcfService;

namespace Cratos.Server.WinService
{
	public partial class CratosWinService : ServiceBase
	{
		#region Class Constant declarations
		#endregion

		#region Class Event declarations
		#endregion

		#region Class Variable declarations
		private bool				startCratosWcfService     = false;
		private bool				startCratosDualWcfService = false;

		private ServiceHost cratosWcfServiceHost;
		private ServiceHost	cratosDualWcfServiceHost;
		#endregion

		#region Class Constructors & Destructors
		/// <summary>
		/// Class Constructor
		/// </summary>
		public CratosWinService()
		{
			// Initialize the relevant components
			InitializeComponent();

			// Subscribe to the relevant events
			CratosWcfService.LogMessage      += new CratosLogMessageEventHandler(this.OnServiceLogMessage);
			CratosDualWcfService.LogMessage  += new CratosLogMessageEventHandler(this.OnServiceLogMessage);

			// Setup the Framework
			DOCratosGlobal.UnityContainer                     = CratosStart.UnityContainer;
			DOCratosGlobal.EntityAccessMethod                 = ConfigurationManager.AppSettings["CratosEntityAccess"];
			DOCratosGlobal.EntityCollectionAccessMethod       = ConfigurationManager.AppSettings["CratosEntityCollectionAccess"];
			DOCratosGlobal.EntityPagingCollectionAccessMethod = ConfigurationManager.AppSettings["CratosEntityPagingCollectionAccess"];
			DOCratosGlobal.DBConnectionName                   = ConfigurationManager.AppSettings["DBConnectionName"];

			// Set the relevant options
			CratosHelper.LogFilename = ConfigurationManager.AppSettings["LogFilename"];
		}
		#endregion

		#region Class Properties
		#endregion

		#region Class Methods
		/// <summary>
		/// Start Service method
		/// </summary>
		public void StartService()
		{
			// Declare the required variables

			// Start all the relevant services
			this.OnStart(null);

			// Return to calling method
			return;
		}

		/// <summary>
		/// Stop Services
		/// </summary>
		public void StopServices()
		{
			// Declare the required variables

			// Start all the relevant services
			this.OnStop();

			// Return to calling method
			return;
		}

		/// <summary>
		/// On Start method
		/// </summary>
		/// <param name="args"></param>
		protected override void OnStart(string[] args)
		{
			// Declare the required variables

			try
			{
				// Log an Informational message
				this.OnServiceLogMessage(CratosLogSeverity.Informational, "Cratos Service", "Starting WCF Service(s)");

				// Extract the relevant configuration items
				this.startCratosWcfService     = (ConfigurationManager.AppSettings["StartCratosWcfService"] == bool.TrueString);
				this.startCratosDualWcfService = (ConfigurationManager.AppSettings["StartCratosDualWcfService"] == bool.TrueString);

				#region Cratos WCF Service
				// Make sure we are allowed to start the service
				if (this.startCratosWcfService)
				{
					// Create and setup the relevant service
					this.cratosWcfServiceHost = new ServiceHost(typeof(CratosWcfService),
																											new Uri(ConfigurationManager.AppSettings["CratosWcfServiceAddress"]));

					// Start the service
					this.cratosWcfServiceHost.Open();

					// Log a message to the UI
					this.LogMessage(CratosLogSeverity.Informational, "Cratos Service", "Cratos WCF Service started");
				}
				#endregion

				#region Cratos Dual WCF Service
				// Make sure we are allowed to start the service
				if (this.startCratosDualWcfService)
				{
					// Create and setup the relevant service
					this.cratosDualWcfServiceHost = new ServiceHost(typeof(CratosDualWcfService),
																													new Uri(ConfigurationManager.AppSettings["CratosDualWcfServiceAddress"]));

					// Start the service
					this.cratosDualWcfServiceHost.Open();

					// Log a message to the UI
					this.LogMessage(CratosLogSeverity.Informational, "Cratos Service", "Cratos Dual WCF Service started");
				}
				#endregion
			}
			catch (Exception runtimeException)
			{
				// Log a message to the UI
				this.LogMessage(CratosLogSeverity.Exception, "Cratos Service", runtimeException.ToString());
			}

			// Return to calling method
			return;
		}

		/// <summary>
		/// On Stop method
		/// </summary>
		protected override void OnStop()
		{
			// Declare the required variables

			try
			{
				// Log an Informational message
				this.OnServiceLogMessage(CratosLogSeverity.Informational, "Cratos Service", "Stopping WCF Service(s)");

				#region Cratos WCF Service
				// Make sure the Service is started
				if (this.cratosWcfServiceHost != null)
				{
					// Stop the service
					this.cratosWcfServiceHost.Close();

					// Log a message to the UI
					this.LogMessage(CratosLogSeverity.Informational, "Cratos Service", "Cratos WCF Service stopped");
				}
				#endregion

				#region Cratos Dual WCF Service
				// Make sure the Service is started
				if (this.cratosDualWcfServiceHost != null)
				{
					// Stop the service
					this.cratosDualWcfServiceHost.Close();

					// Log a message to the UI
					this.LogMessage(CratosLogSeverity.Informational, "Cratos Service", "Cratos Dual WCF Service stopped");
				}
				#endregion
			}
			catch (Exception runtimeException)
			{
				// Log a message to the UI
				this.LogMessage(CratosLogSeverity.Exception, "Cratos Service", runtimeException.ToString());
			}

			// Return to calling method
			return;
		}
		#endregion

		#region Class Support Methods
		private void OnServiceLogMessage(CratosLogSeverity msgSeverity, string msgSource, string newMessage)
		{
			// Declare the required variables

			// Log the incoming message
			this.LogMessage(msgSeverity, msgSource, newMessage);

			// Return to calling method
			return;
		}

		private void LogMessage(CratosLogSeverity msgSeverity, string msgSource, string newMessage)
		{
			// Declare the required variables

			// Log a message to the UI if required
			if (!CratosStart.IsService)
			{
				Console.WriteLine(string.Format("[{0}] [{1} - {2}] {3}", DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss"),
																																 msgSeverity.ToString(), msgSource, newMessage));
			}

			// Create an event log entry
			switch (msgSeverity)
			{
				case CratosLogSeverity.Exception:
					EventLog.WriteEntry(msgSource, newMessage, EventLogEntryType.Error);

					break;

				case CratosLogSeverity.Warning:
				case CratosLogSeverity.Informational:
				case CratosLogSeverity.ValidationError:
					if (Convert.ToBoolean(ConfigurationManager.AppSettings["LogToEventLog"]))
					{
						EventLog.WriteEntry(msgSource, newMessage, EventLogEntryType.Information);
					}

					break;
			}

			// Return to calling method
			return;
		}
		#endregion
	}
}
